#pragma once

#include <iostream>
#include <string>
#include <memory>
#include "Epoller.hpp"
#include "Socket.hpp"
#include "Connection.hpp"
#include "Log.hpp"
#include "HandlerConnection.hpp"

using namespace socket_ns;

class Listener
{
public:
    Listener(uint16_t port, HandlerConnection &hc)
        : _port(port),
          _listensock(std::make_unique<TcpSocket>()),
          _hc(hc)
    {
        InterAddr addr("0", _port);
        _listensock->BuidListenSocket(addr);
    }

    void Accepter(Connection *conn)
    {
        // LOG(DEBUG, "Get a new link, conn fd:%d\n", conn->Sockfd());
        while (true)
        {
            InterAddr addr;
            int code = 0;
            int sockfd = _listensock->Accpeter(&addr, &code);
            if (sockfd >= 0)
            {
                conn->_R->AddConnection(
                    sockfd,
                    EPOLLIN | EPOLLET,
                    std::bind(&HandlerConnection::HandlerRecv, &_hc, std::placeholders::_1),
                    std::bind(&HandlerConnection::HandlerSender, &_hc, std::placeholders::_1),
                    std::bind(&HandlerConnection::HandlerExcepter, &_hc, std::placeholders::_1));
                    LOG(INFO, "AddConnection fd : %d success...\n", sockfd);
            }
            else
            {
                // 底层链接已经获取完了
                if (code == EWOULDBLOCK || code == EAGAIN)
                {
                    LOG(DEBUG, "accepter all link...\n");
                    break;
                }
                else if (code == EINTR) // 被信号中断了
                {
                    LOG(DEBUG, "accepter interupt by signal...\n");
                    continue;
                }
                else
                {
                    LOG(ERROR, "accepter error...\n");
                    break;
                }
            }
        }
    }
    int Sockfd()
    {
        return _listensock->SockFd();
    }
    ~Listener()
    {
        _listensock->Close();
    }

private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensock;
    HandlerConnection &_hc;
};